package com.hzit.common.aspect;

import com.alibaba.fastjson.JSON;
import com.hzit.common.annota.RequiresPermissions;
import com.hzit.common.constants.TokenConstants;
import com.hzit.common.entity.LoginUser;
import com.hzit.common.exeption.NotPermissionException;
import com.hzit.common.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.naming.NoPermissionException;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Component
@Aspect
public class HzitAuthAspect {
	@Autowired
	private StringRedisTemplate redisTemplate;

	// AOP的环绕通知处理：
	@Around("@annotation(permissions)")
	public Object around(ProceedingJoinPoint joinPoint, RequiresPermissions permissions) throws Throwable{
		//1. 得到自定义注解中的权限串
		String[] value = permissions.value();
		//2. 我们假定只有一个权限串，我们取出第一个即可
		String permission = "";
		if(value != null && value.length > 0){
			permission = value[0];
		}
		//3. 得到登录用户
		LoginUser user = getLoginUser();
		//4. 得到权限串
		List<String> permissionList = user.getPermissions();
		//5. 对比我们注解上定义权限串与上面的集合中的权限串，如果在集合中存在此权限串，证明有权访问，否则，无权限访问，抛出异常！
		boolean b = hasRights(permission,permissionList);
		if(!b){
			throw new NotPermissionException("无权限访问!");
		}
		//调用方法
		try {
			return joinPoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
			throw e;
		}

	}
	// 判断是否有访问权限
	private boolean hasRights(String permission, List<String> permissionList) {
		return permissionList.contains(permission);
	}

	// 得到登录用户
	private LoginUser getLoginUser() {
		//1. 得到请求对象
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();
		//2. 得到请求头
		String header = request.getHeader(TokenConstants.LOGIN_AUTH_HEADER);
		if (header.startsWith(TokenConstants.LOGIN_AUTH_BEARER)) {
			//2.1  获取到请求头中携带的jwt加密信息
			String token = header.replaceAll(TokenConstants.LOGIN_AUTH_BEARER, "");
			//2.2  解析token
			Claims claims = JwtUtil.parseToken(token);
			if(claims != null){
				//2.3  得到uuid
				String uuid = claims.get(TokenConstants.USER_KEY).toString();
				//2.4 构造redis的key
				String key = getKey(uuid);
				//2.5 从redis中根据key得到值
				String s = redisTemplate.opsForValue().get(key);
				//2.6 转换为loginUser对象
				return JSON.parseObject(s,LoginUser.class);
			}

		}
		return null;
	}
	// 获取到redis的key
	private String getKey(String uuid) {
		return TokenConstants.LOGIN_USER_REDIS_KEY + uuid;
	}
}
